<?php
/**
 * @name /lib/private/Donation.php
 * @author Michael Foss <michael@mikefoss.com>
 * @version 2011.03.31
 *
 * A Donation class to manage donations.
 *
 */

/**
 * Donation class.
 *
 */
ReqLib('/lib/private/User.php');
ReqLib('/lib/private/DonatedItem.php');
ReqLib('/lib/private/Notification.php');

class Donation {
  /**
   * Donation identification.
   *
   * @var integer
   */
  var $DonationId;
  /**
   * DonatedItem notes.
   *
   * @var string
   */
  var $Notes;
  /**
   * The unix timestamp the donation was submitted.
   *
   * @var integer
   */
  var $DateDonated;
  /**
   * The user that placed the donation.
   *
   * @var User
   */
  var $User;
  /**
   * The donated items.
   *
   * @var DonatedItem[]
   */
  var $DonatedItems;

  /* Methods:

	"GET":
	Donation[] GetDonations(int offset, int maxResults)
	bool Exists(int DonationId)
	string ToString()

	"SCUD":
	bool Load(int donationId)
	bool Create(userId)
	bool Save()
	static bool Delete(int donationId)

	Custom:
	static int[] GetDonationIdsByUserId(userId)
	static int[] GetDonationIdsByItemId(itemId)
  int GetLastDateReceived()

	*/


  /**
  *
  * Constructor.
  *
  */
  function Donation(){
    $this->DonationId = 0;
    $this->Notes = '';
    $this->DateDonated = 0;
    $this->User = new User();
    $this->DonatedItems = array();
  }

  /**
   * Generates a list of Donations.
   *
   * @param int
   * @param int
   * @return Donation[]
   */
	function GetDonations($offset = 0, $maxResults = 0){
		$objects = array();
		$db = new DB();
		// Initial query
		$query = "SELECT DonationId FROM donations ORDER BY DateDonated DESC;";
		// Look for max results and offsets
		if ($maxResults && $maxResults * 1 == $maxResults) {
		$query .= " LIMIT $maxResults";
		if ($offset && $offset * 1 == $offset)
			$query .= " OFFSET $offset";
		}
		elseif ($offset && $offset * 1 == $offset)
		$query .= " LIMIT 99999999 OFFSET $offset";
		// Get the ids
		$ids = $db->QueryCol($query);
		// If we have ids, load the objects
		if (is_array($ids))
		foreach ($ids as $id) {
			$objects[count($objects)] = new Donation();
			$objects[count($objects) - 1]->Load($id);
		}
		return $objects;
	}

  /**
   * Determines if a item exists or not.
   *
   * @param integer
   * @return boolean
   */
  function Exists($donationId){
    $db = new DB();
    return ($db->QueryVal("SELECT DonationId FROM donations WHERE DonationId='" . addslashes($donationId) . "' LIMIT 1;") > 0);
  }

  /**
  * Lists the attributes about a Donation.
  *
  * @return string
  */
  function ToString($del = '<br />'){
    $str = "";
    $str .= 'DonatedId = ' . $this->DonationId . $del;
    $str .= 'Notes = ' . $this->Notes . $del;
    $str .= 'DateDonated = ' . date('m/d/Y h:i J', $this->DateDonated) . $del;
    $str .= 'User = ' . $this->User->ToString($del);
    for ($i = 0; $i < count($this->DonatedItems); $i++)
      $str .= 'DonatedItems[' . $i . ']: = ' . $this->DonatedItems[$i]->ToString($del);
    return $str;
  }

  /**
    * Loads the Donation information;
    * Returns a true on success, a false on failure.
    *
    * @param integer
    * @return boolean
    */
  function Load($donationId){
    if (!Donation::Exists($donationId))
      return false;
    else{
      $db = new DB();
      $id = addslashes($donationId);
      $sql = <<<HEREDOC
        SELECT
          DonationId,
          UserId,
          UNIX_TIMESTAMP(DateDonated) AS DateDonated,
          Notes
        FROM
          donations
        WHERE
          DonationId=$id;
HEREDOC;
      $data = $db->QueryRow($sql);
      $this->User = new User();
      if (!$this->User->Load($data["UserId"]))
        return false;
      $this->DonationId = $data["DonationId"];
      $this->DateDonated = $data["DateDonated"];
      $this->Notes = $data["Notes"];
      $this->DonatedItems = DonatedItem::GetDonatedItemsByDonationId($this->DonationId);
      return true;
    }
  }

  /**
   * Creates a Donation;
   * returns true on success, false on failure.
   *
   * @param int
   * @return boolean
   */
  function Create($userId){
    if (!User::Exists($userId))
      return false;
    $db = new DB();
    $this->DateDonated = time();
    $sql =
      "INSERT INTO donations (UserId, DateDonated, Notes) VALUES (" .
      "'" . addslashes($userId) ."', " .
      "'" . date('Y-m-d', $this->DateDonated) . "', " .
      "'');";
    $db->Query($sql);
    $sql = "SELECT LAST_INSERT_ID();";
    $this->DonationId = $db->QueryVal($sql);
    $this->User = new User();
    $this->User->Load($userId);
    $this->Save();
      $msg = 'Thank you for your donation. Your donation id is ' . $this->DonationId . '.

If you have any questions regarding your donation,
please go to ' . _webroot('/faq.php#Donations') . '
or call us directly.

To review your donations, go to ' . _webroot('/donations/') . '.

Send the packages to the following address:
123 Any Street
Somewhereville, XX  12345  USA
';
      // Send the user an email
      mail(
        '"' . $this->User->FirstName . ' ' . $this->User->LastName . '" <' . $this->User->Email . '>',
        'WACAP Thanks You For Your Donation (Donation Id ' . $this->DonationId . ')',
        $msg,
        'From: donations@wacap.org'
      );
      // Notify the admin
      $n = new Notification();
      $n->Create('New Donation ("' . $this->User->FirstName . ' ' . $this->User->LastName . '")', '<p>This message was sent to the user:</p><code>' . str_replace($msg, '\r\n', '<br />') . '</code>');
  }

  /**
   * Saves a Donation;
   * for each donated item, if there is no item id and it is not verified,
   * will create a new item in the DB;
   * returns true on success, false on failure.
   *
   * @return boolean
   */
  function Save() {
    if (!Donation::Exists($this->DonationId) || !User::Exists($this->User->UserId))
      return false;

    // Update the donation wrapper data
		$db = new DB();
    $db->Query("
      UPDATE donations SET
      UserId='" . addslashes($this->User->UserId) . "',
      DateDonated='" . date('Y-m-d', $this->DateDonated) . "',
      Notes='" . addslashes($this->Notes) . "'
      WHERE DonationId='" .addslashes($this->DonationId) . "';
    ");

    // Determine which donated item ids to delete and delete them
    $donatedItemIds = Donation::GetDonatedItemIds($this->DonationId);
    $deletedItemIds = array_diff($donatedItemIds, $this->GetDonatedItemIds());
    if (count($deletedItemIds))
      foreach ($deletedItemIds as $id)
        DonatedItem::Delete($id);

    // Save the current donated items
    foreach ($this->DonatedItems as $donatedItem)
      if (!DonatedItem::Exists($donatedItem->DonatedItemId))
        $donatedItem->Create($this->DonationId, $donatedItem->ItemId);
      else
        $donatedItem->Save();
  }

  /**
   * Gets all donated item ids in the object or the record.
   *
   * @static optional
   * @protected
   * @param $donationId
   * @return integer[]
   */
  function GetDonatedItemIds($donationId = 0) {
    if ($donationId) {
      $db = new DB();
      $donatedItemIds = $db->QueryCol("SELECT di.DonatedItemId FROM donateditems di WHERE di.DonationId='" . addslashes($donationId) . "';");
      if (!$donatedItemIds)
        $donatedItemIds = array();
    }
    else {
      $donatedItemIds = array();
      foreach ($this->DonatedItems as $donatedItem)
        $donatedItemIds[] = $donatedItem->DonatedItemId;
    }
    return $donatedItemIds;
  }

  /**
   * Deletes a Donation;
   * returns true on success, false on failure.
   *
   * @static
   * @param integer
   * @return boolean
   */
  function Delete($donationId){
    $donation = new Donation();
    if (!$donation->Load($donationId))
      return false;
    $db = new DB();
    $donatedItemIds = Donation::GetDonatedItemIds($donationId);
    foreach ($donatedItemIds as $id)
      DonatedItem::Delete($id);
    $sql = "DELETE FROM donations WHERE DonationId='" . addslashes($donationId) . "' LIMIT 1;";
    $db->Query($sql);
    return true;
  }

  /**
  * STATIC METHOD
  * Gets all donation ids that have a specific user id.
  *
  * @param integer
  * @return integer[]
  */
  function GetDonationIdsByUserId($userId){
    $db = new DB();
    $donationIds = $db->QueryCol("SELECT DonationId FROM donations WHERE UserId='" . addslashes($userId) . "' ORDER BY DateDonated DESC;");
    if (!$donationIds)
      $donationIds = array();
    return $donationIds;
  }

  /**
  * STATIC METHOD
  * Gets all donation ids that have a specific item id.
  *
  * @param integer
  * @return integer[]
  */
  function GetDonationIdsByItemId($itemId){
    $donationIds = array();
    $db = new DB();
    $donationIds = $db->QueryCol("SELECT DonationId FROM donateditems WHERE ItemId= '" .addslashes($itemId) . "' ORDER BY DateDonated DESC;");
    return $donationIds;
	}

  /**
   * Given an existing item in the Donation,
   * removes it and reassigns it as a new item;
   * returns true on success, false on failure.
   *
   * @param Item
   * @param Item
   * @return boolean
   */
  function ReassignDonatedItem($existingItem, $newItem) {
  }

  /**
   * Gets the number of items in all donated items.
   *
   * @return integer
   */
  function GetDonatedItemsPledgedCount() {
    $count = 0;
    foreach ($this->DonatedItems as $di)
      $count += $di->QuantityPledged;
    return $count;
  }

  /**
   * Gets the number of items in all donated items.
   *
   * @return integer
   */
  function GetDonatedItemsReceivedCount() {
    $count = 0;
    foreach ($this->DonatedItems as $di)
      $count += $di->QuantityReceived;
    return $count;
  }

  /**
   * Gets the last date a package was received.
   *
   * @return integer
   */
  function GetLastDateReceived() {
    $max = 0;
    foreach ($this->DonatedItems as $di)
      $max = max($max, $di->LastDateReceived);
    return $max;
  }
}